package com.tao.power.Service.ServiceImpl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.tao.power.Dao.UserMapper;
import com.tao.power.Dto.ImportFailDto;
import com.tao.power.Dto.Result;
import com.tao.power.Dto.UserRolesDto;
import com.tao.power.Enums.ErrorEnums;
import com.tao.power.Enums.StatusEnums;
import com.tao.power.Pojo.Roler;
import com.tao.power.Pojo.User;
import com.tao.power.Pojo.UserRoler;
import com.tao.power.Service.UserService;
import com.tao.power.Utils.SystemExceptionNew;
import com.tao.power.Utils.verifyUtils;
import com.tao.power.config.AuthorityAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private verifyUtils verifyUtils;

    /**
     * 导入的定制用户的列
     */
//    private static final String[] importUserColumns = {"用户名", "密码", "姓名", "性别", "联系电话", "邮箱", "创建时间", "最后修改时间", "状态", "备注"};
    /**
     * 导出的定制用户的列
     */
    private static final String[] importFailUserColumns = {"用户名", "密码", "姓名", "性别", "联系电话", "邮箱", "状态", "备注", "失败原因"};
    private static final String[] importFailUserInfoColumns = {"username", "password", "name", "gender", "telephone", "email", "status", "remarks","fail"};


    private static final String[] exportUserColumns = {"编号", "用户名", "密码", "姓名", "性别", "联系电话", "邮箱", "创建时间", "最后修改时间", "状态", "备注"};
    private static final String[] exportUserInfoColumns = {"id", "username", "password", "name", "gender", "telephone", "email", "startTime", "endTime", "status", "remarks"};


    private static final String[] importUserMoBanColumns = {"用户名", "密码", "姓名", "性别", "联系电话", "邮箱", "状态", "备注"};

    @Override
    public Result insertUser(User user) {
        if (user == null) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        verifyUtils.userVerify(user);
        Date date = new Date();
        user.setStartTime(date);
        int count = userMapper.insertUser(user);
        if (count == 0) {
            return Result.fail(ErrorEnums.AddInFO_Fail.getLabel(), ErrorEnums.AddInFO_Fail.getValue());
        }
        return Result.ok("", ErrorEnums.Success.getValue());
    }

    @Override
    public Result queryUser(int count, int page) {
        int index = count * (page - 1);
        List<User> userList = userMapper.queryUser(index, count);
        return Result.ok("", userList, (long) userMapper.queryUserTotal(), ErrorEnums.Success.getValue());
    }

    @Override
    public Result updateUser(User user) {
        verifyUtils.userVerify(user);
        return getResult(user);
    }

    @Override
    @Transactional
    public Result deleteUser(Integer id) {
        if (id == null) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        int count = userMapper.deleteUser(id);
        int deleteUserRoles = userMapper.deleteUserRoles(id);
        if (count == 0 && deleteUserRoles == 0) {
            throw new SystemExceptionNew(ErrorEnums.Deleteinfo_Fail.getValue(), ErrorEnums.Deleteinfo_Fail.getLabel());
        }
        return Result.ok("", ErrorEnums.Success.getValue());
    }

    @Override
    public Result queryUserBySearch(String username, String name, String status,
                                    Date startTime, Date endTime, Integer currentPage, Integer pageSize) {
        int count = pageSize * (currentPage - 1);
        List<User> userList = userMapper.queryUserBySearch(username, name, status, startTime, endTime, count, pageSize);

        return Result.ok("", userList, (long) userMapper.queryUserBySearchTotal(username, name, status, startTime, endTime),
                ErrorEnums.Success.getValue());
    }

    @Override
    public void exportUser(List<Integer> idList, HttpServletResponse response) throws Exception {
        ServletOutputStream outputStream = response.getOutputStream();
        ExcelWriter writer = ExcelUtil.getWriter(true);
        try {
            List<User> userList = userMapper.exportUser(idList);
            for (User user : userList) {
                user.setStatus(StatusEnums.getLabelByValue(user.getStatus()));
                user.setPassword(DesensitizedUtil.password(user.getPassword()));
            }
//            writer.addHeaderAlias("id", "编号");
//            writer.addHeaderAlias("username", "用户名");
//            writer.addHeaderAlias("password", "密码");
//            writer.addHeaderAlias("name", "姓名");
//            writer.addHeaderAlias("gender", "性别");
//            writer.addHeaderAlias("telephone", "联系电话");
//            writer.addHeaderAlias("email", "邮箱");
//            writer.addHeaderAlias("startTime", "创建时间");
//            writer.addHeaderAlias("endTime", "失效时间");
//            writer.addHeaderAlias("status", "状态");
//            writer.addHeaderAlias("remarks", "备注");
            for (int i = 0; i < exportUserColumns.length; i++) {
                writer.addHeaderAlias(exportUserInfoColumns[i], exportUserColumns[i]);
            }
            writer.write(userList, true);
            response.setContentType("application/vnd.openxmlformats-officedomucent.spreadsheetml.sheet;charset:utf-8");
            String fileName = URLEncodeUtil.encode("用户信息");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            writer.flush(outputStream, true);
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            outputStream.close();
            writer.close();
        }
    }

    @Override
    public Result importUser(MultipartFile multipartFile, HttpServletResponse response) throws IOException {
        if (multipartFile==null){
            return Result.fail(ErrorEnums.FileEmpty.getLabel(),ErrorEnums.FileEmpty.getValue());
        }
        InputStream in = multipartFile.getInputStream();
        ExcelReader excelReader = ExcelUtil.getReader(in);
        List<List<Object>> importList = excelReader.read(1);
        List<User> userList = new ArrayList<>();
//        List<ImportFailDto> failImport = new ArrayList<>();
        Date date = new Date();
        for (List<Object> row : importList) {
            User user = new User();
            user.setUsername(row.get(0).toString());
            user.setPassword(row.get(1).toString());
            user.setName(row.get(2).toString());
            user.setGender(row.get(3).toString());
            user.setTelephone(row.get(4).toString());
            user.setEmail(row.get(5).toString());
            user.setStartTime(date);
            if (row.get(6).toString().equals("有效")) {
                user.setStatus("1");
            }
            if (row.get(6).toString().equals("无效")) {
                user.setStatus("0");
            }
            user.setRemarks(row.get(7).toString());
            boolean b = verifyUtils.importVerify(user);
            if (!b) {
//                ImportFailDto importFailDto = new ImportFailDto();
//                importFailDto.setUser(user);
//                importFailDto.setFail(b);
//                failImport.add(importFailDto);
                continue;
            }
            userList.add(user);
        }
        //导入失败，返回错误数据
//        if (!failImport.isEmpty()) {
//            ExcelWriter writer = ExcelUtil.getWriter(true);
//            ServletOutputStream out = response.getOutputStream();
//            try {
//                for (int i = 0; i < importFailUserColumns.length; i++) {
//                    writer.addHeaderAlias(importFailUserInfoColumns[i], importFailUserColumns[i]);
//                }
//                writer.write(failImport, true);
//                //out为OutputStream，需要写出到的目标流
//                //response为HttpServletResponse对象
////                response.setContentType("application/vnd.openxmlformats-officedomucent.spreadsheetml.sheet;charset:utf-8");
//                //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
//                response.setHeader("Content-Disposition", "attachment;filename=test.xlsx");
//            } catch (Exception e) {
//                e.printStackTrace();
//            } finally {
//                writer.flush(out, true);
//                // 关闭writer，释放内存
//                writer.close();
//                //此处记得关闭输出Servlet流
//                IoUtil.close(out);
//            }
//        }
        if (userList.isEmpty()){
            return Result.fail(ErrorEnums.ImportFail.getLabel(), ErrorEnums.ImportFail.getValue());
        }
        userMapper.saveBatchUser(userList);
        int fail = importList.size() - userList.size();
        return Result.ok("导入数据成功，导入" + userList.size() + "数据，失败" + fail + "条数据!", ErrorEnums.Success.getValue());
    }

    @Override
    @Transactional
    public Result setRoles(UserRolesDto userRolesDto) {
        if (userRolesDto == null) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        List<UserRoler> list = userMapper.queryRolerById(userRolesDto.getUserId());
        List<Integer> addUserRoler = list.stream().map(UserRoler::getRolerId).collect(Collectors.toList());
        List<Integer> deleteUserRoler = userRolesDto.getRolerInfo().stream().map(Roler::getId).collect(Collectors.toList());
        List<Integer> clone = ObjectUtil.clone(deleteUserRoler);
        //前端移除后端相同的字段，剩余的是新增的
        deleteUserRoler.removeAll(addUserRoler);
        //后端移除前端相同的字段
        addUserRoler.removeAll(clone);
        int addCount = 0, delCount = 0;
        if (!deleteUserRoler.isEmpty()) {
            addCount = userMapper.setRoles(deleteUserRoler, userRolesDto.getUserId());
        }
        if (!addUserRoler.isEmpty()) {
            delCount = userMapper.deleteRoles(addUserRoler, userRolesDto.getUserId());
        }
        if (addCount == 0 && delCount == 0) {
            throw new SystemExceptionNew(ErrorEnums.Info_Fail.getValue(), ErrorEnums.Info_Fail.getLabel());
        }
        return Result.ok("", ErrorEnums.Success.getValue());
    }

    @Override
    @Transactional
    public Result batchDel(List<Integer> idList) {
        if (idList.isEmpty()) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        List<Integer> list = idList.stream().distinct().collect(Collectors.toList());
        int count = userMapper.BatchDel(list);
        int batchDelete = userMapper.batchDeleteUserRoles(list);
        if (count == 0 && batchDelete == 0) {
            throw new SystemExceptionNew(ErrorEnums.Deleteinfo_Fail.getValue(), ErrorEnums.Deleteinfo_Fail.getLabel());
        }
        return Result.ok("", ErrorEnums.Success.getValue());
    }

    @Override
    public Result queryRolerById(Integer id) {
        if (id == null) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        List<UserRoler> list = userMapper.queryRolerById(id);
        return Result.ok("", list, ErrorEnums.Success.getValue());
    }

    @Override
    public void uploadMoBan(HttpServletResponse response) throws Exception {
        ServletOutputStream outputStream = response.getOutputStream();
        ExcelWriter writer = ExcelUtil.getWriter(true);
        try {
//            writer.writeCellValue(1, 0, "用户名");
//            writer.writeCellValue(2, 0, "密码");
//            writer.writeCellValue(3, 0, "姓名");
//            writer.writeCellValue(4, 0, "性别");
//            writer.writeCellValue(5, 0, "联系电话");
//            writer.writeCellValue(6, 0, "邮箱");
//            writer.writeCellValue(7, 0, "状态");
//            writer.writeCellValue(8, 0, "备注");
            for (int i = 0; i < importUserMoBanColumns.length; i++) {
                writer.writeCellValue(i, 0, importUserMoBanColumns[i]);
            }
            response.setContentType("application/vnd.openxmlformats-officedomucent.spreadsheetml.sheet;charset:utf-8");
            String fileName = URLEncodeUtil.encode("用户信息模板");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            writer.flush(outputStream, true);
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            outputStream.close();
            writer.close();
        }
    }

    @Override
    public Result updateStatus(User user) {
        if (user == null) {
            return Result.fail(ErrorEnums.InfoIsEmpty.getLabel(), ErrorEnums.InfoIsEmpty.getValue());
        }
        return getResult(user);
    }

    private Result getResult(User user) {
        Date date = new Date();
        user.setEndTime(date);
        int count = userMapper.updateUser(user);
        if (count == 0) {
            return Result.fail(ErrorEnums.Info_Fail.getLabel(), ErrorEnums.Info_Fail.getValue());
        }
        return Result.ok("", ErrorEnums.Success.getValue());
    }
}
